#include "simulation.h"

#include <draw_2d.h>
#include <log.h>
#include <stdio.h>

////////////////////////////////////////////////////////////////////////////////

Simulation::Simulation(const SimulationParameters& parameters)
{
  _done = false;
  _winner = -1;
  
  _screen_dim = parameters.screen_dim;
  _width = parameters.screen_dim.w;
  _height = parameters.screen_dim.h;
  
  _bounds.set(0.0f, 0.0f, _width, _height);
  
  _food_timer = 0;
  _eat_timer = 0;
  
  _num_players = parameters.num_players;
  
  for (unsigned i = 0; i < _num_players; i++)
  {
    _player[i].alive = true;
    _player[i].food = SIM_START_FOOD;
    _player[i].colour = parameters.player_colour[i];
    _player[i].ai = parameters.ai[i];
  }
  
  _num_food = 0;
  _num_bullets = 0;
  _num_microbes = 0;
  
  for (unsigned i = 0; i < parameters.num_players; i++)
  {
    Vector2 pos;
    float angle = Rand_float(0.0f, 360.0f);
    
    pos.x = Rand_float(20.0f, _width - 20.0f);
    pos.y = Rand_float(20.0f, _height - 20.0f);
    
    addMicrobe(MICROBE_SPEEDY, i, pos, angle);
  }
}

Simulation::~Simulation()
{
  for (unsigned i = 0; i < _num_players; i++)
  {
    delete _player[i].ai;
  }
}

void Simulation::update(unsigned dM, float dT)
{
  if (_done)
  {
    return;
  }
  
  thinkMicrobes(dM, dT);
  orderMicrobes(dM, dT);
  collideMicrobes();
  
  updateBullets(dT);
  removeDeadBullets();
  
  _food_timer += dM;
  if (_food_timer >= SIM_FOOD_TIME)
  {
    _food_timer -= SIM_FOOD_TIME;
    
    Vector2 pos;
    
    pos.x = Rand_float(20.0f, _width - 20.0f);
    pos.y = Rand_float(20.0f, _height - 20.0f);
    
    addFood(pos);
  }
  
  _eat_timer += dM;
  if (_eat_timer >= SIM_EAT_TIME)
  {
    _eat_timer -= SIM_EAT_TIME;
    
    eatFood();
  }
  
  removeDeadFood();
  removeDeadMicrobes();
  
  calcDone();
}

void Simulation::onChangeDim(const Dimension& dim)
{
  //_width = dim.w;
  //_height = dim.h;
}

void Simulation::draw()
{
  Graphics_pushOrthoView(0.0f, _width, _height, 0.0f);
  
  for (unsigned i = 0; i < _num_food; i++)
  {
    Draw2D_fillCircle(_food[i].pos, SIM_FOOD_RADIUS, 12, Colour::RED);
  }
  
  for (unsigned i = 0; i < _num_microbes; i++)
  {
    drawMicrobeSight(&_microbe[i]);
  }
  
  for (unsigned i = 0; i < _num_microbes; i++)
  {
    drawMicrobe(&_microbe[i]);
  }
  
  drawBullets();
  
  Graphics_popView();
  
  drawStats();
  
  if (_done)
  {
    drawGameInfo();
  }
}

void Simulation::addFood(const Vector2& pos)
{
  if (_num_food >= SIM_MAX_FOOD)
  {
    return;
  }
  
  _food[_num_food].id = _food_id_gen.genId();
  _food[_num_food].alive = true;
  _food[_num_food].pos = pos;
  
  _num_food++;
}

void Simulation::removeDeadFood()
{
  unsigned old_num_food = _num_food;
  
  _num_food = 0;
  
  for (unsigned i = 0; i < old_num_food; i++)
  {
    if (_food[i].alive)
    {
      _food[_num_food++] = _food[i];
    }
    else
    {
      _food_id_gen.delId(_food[i].id);
    }
  }
}

void Simulation::addBullet(unsigned player_id, const Vector2& pos, float angle)
{
  if (_num_bullets >= SIM_MAX_MICROBES)
  {
    return;
  }
  
  _bullet[_num_bullets].pos = pos;
  _bullet[_num_bullets].angle = angle;
  _bullet[_num_bullets].time = BULLET_TIME;
  _bullet[_num_bullets].player_id = player_id;
  _bullet[_num_bullets].alive = true;
  
  _num_bullets++;
}

void Simulation::updateBullets(float dT)
{
  for (unsigned i = 0; i < _num_bullets; i++)
  {
    _bullet[i].pos.x += BULLET_SPEED * Math_cosd(_bullet[i].angle) * dT;
    _bullet[i].pos.y += BULLET_SPEED * Math_sind(_bullet[i].angle) * dT;
    _bullet[i].time -= dT;
    
    if (_bullet[i].time <= 0.0f)
    {
      _bullet[i].alive = false;
    }
    else
    {
      for (unsigned j = 0; j < _num_microbes; j++)
      {
        if (_microbe[j].player_id == _bullet[i].player_id)
        {
          continue;
        }
        
        if (_microbe[j].body.contains(_bullet[i].pos))
        {
          _bullet[i].alive = false;
          _microbe[j].alive = false;
          
          break;
        }
      }
    }
  }
}

void Simulation::removeDeadBullets()
{
  unsigned old_num_bullets = _num_bullets;
  
  _num_bullets = 0;
  
  for (unsigned i = 0; i < old_num_bullets; i++)
  {
    if (_bullet[i].alive)
    {
      _bullet[_num_bullets++] = _bullet[i];
    }
  }
}

void Simulation::addMicrobe(MicrobeType type, unsigned player_id,
  const Vector2& pos, float angle)
{
  if (_num_microbes >= SIM_MAX_MICROBES)
  {
    return;
  }
  
  _microbe[_num_microbes].type = type;
  _microbe[_num_microbes].id = _microbe_id_gen.genId();
  _microbe[_num_microbes].player_id = player_id;
  _microbe[_num_microbes].angle = angle;
  _microbe[_num_microbes].alive = true;
  _microbe[_num_microbes].action = MICROBE_ACTION_NONE;
  _microbe[_num_microbes].action_time = 0;
  
  if (type == MICROBE_SPEEDY)
  {
    _microbe[_num_microbes].body.set(pos, SPEEDY_MICROBE_RADIUS);
    _microbe[_num_microbes].sight = SPEEDY_MICROBE_SIGHT_RADIUS;
  }
  else if (type == MICROBE_SOLDIER)
  {
    _microbe[_num_microbes].body.set(pos, SOLDIER_MICROBE_RADIUS);
    _microbe[_num_microbes].sight = SOLDIER_MICROBE_SIGHT_RADIUS;
  }
  else
  {
    _microbe[_num_microbes].body.set(pos, BIG_DADDY_MICROBE_RADIUS);
    _microbe[_num_microbes].sight = BIG_DADDY_MICROBE_SIGHT_RADIUS;
  }
  
  _num_microbes++;
}

void Simulation::thinkMicrobes(int dM, float dT)
{
  AIData data;
  bool enemy_visible[SIM_MAX_MICROBES];
  MicrobeOrder* order[SIM_MAX_MICROBES];
  
  data.bounds = _bounds;
  
  for (unsigned i = 0; i < _num_microbes; i++)
  {
    _order[i].turn = 0.0f;
    _order[i].move = 0.0f;
    _order[i].angle = 0;
    _order[i].attack = false;
    _order[i].reproduce = false;
    _order[i].evolve = false;
  }
  
  for (unsigned i = 0; i < _num_players; i++)
  {
    if (!_player[i].ai)
    {
      continue;
    }
    
    memset(enemy_visible, 0, sizeof(enemy_visible));
    
    data.player_food = _player[i].food;
    data.num_microbes = 0;
    
    for (unsigned j = 0; j < _num_microbes; j++)
    {
      if (_microbe[j].player_id != i)
      {
        continue;
      }
    
      data.microbe[data.num_microbes] = &_microbe[j];
      
      order[data.num_microbes++] = &_order[j];
      
      for (unsigned k = 0; k < _num_microbes; k++)
      {
        if (_microbe[k].player_id == i)
        {
          continue;
        }
        
        if (_microbe[j].type == MICROBE_SOLDIER)
        {
          Arc sight_arc(_microbe[j].body.pos, _microbe[j].sight,
            _microbe[j].angle - 45.0f, _microbe[j].angle + 45.0f);
          
          if (sight_arc.intersect(_microbe[k].body))
          {
            enemy_visible[k] = true;
          }
        }
        else
        {
          Circle sight_circle(_microbe[j].body.pos, _microbe[j].sight);
          
          if (sight_circle.intersect(_microbe[k].body))
          {
            enemy_visible[k] = true;
          }
        }
      }
    }
    
    data.num_enemies = 0;
    
    for (unsigned j = 0; j < _num_microbes; j++)
    {
      if (enemy_visible[j])
      {
        data.enemy[data.num_enemies++] = &_microbe[j];
      }
    }
    
    data.num_food = 0;
    
    for (unsigned j = 0; j < _num_food; j++)
    {
      if (!_food[j].alive)
      {
        continue;
      }
      
      for (unsigned k = 0; k < data.num_microbes; k++)
      {
        if (data.microbe[k]->type == MICROBE_SOLDIER)
        {
          Arc sight_arc(data.microbe[k]->body.pos, data.microbe[k]->sight,
            data.microbe[k]->angle - 45.0f, data.microbe[k]->angle + 45.0f);
          
          if (sight_arc.contains(_food[j].pos))
          {
            data.food[data.num_food++] = &_food[j];
          }
        }
        else
        {
          Circle sight_circle(data.microbe[k]->body.pos, data.microbe[k]->sight);
          
          if (sight_circle.contains(_food[j].pos))
          {
            data.food[data.num_food++] = &_food[j];
          }
        }
      }
    }
    
    _player[i].ai->think(data, order, dM, dT);
  }
}

void Simulation::orderMicrobes(int dM, float dT)
{
  _num_reproducing_microbes = 0;
  _num_evolving_microbes = 0;
  
  for (unsigned i = 0; i < _num_microbes; i++)
  {
    if (_microbe[i].type == MICROBE_SPEEDY)
    {
      orderSpeedyMicrobe(i, dM, dT);
    }
    else if (_microbe[i].type == MICROBE_SOLDIER)
    {
      orderSoldierMicrobe(i, dM, dT);
      
      if (_microbe[i].action == MICROBE_ACTION_ATTACKING ||
          _microbe[i].action == MICROBE_ACTION_RELOADING)
      {
        handleSoldierAttack(i);
      }
    }
    else
    {
      orderBigDaddyMicrobe(i, dM, dT);
    }
    
    for (unsigned j = 0; j < _num_food; j++)
    {
      if (_food[j].alive && _microbe[i].body.contains(_food[j].pos))
      {
        _food[j].alive = false;
        
        _player[_microbe[i].player_id].food += SIM_FOOD_VALUE;
      }
    }
    
    if (!_microbe[i].body.containedWithin(_bounds))
    {
      _microbe[i].alive= false;
    }
  }
  
  for (unsigned i = 0; i < _num_reproducing_microbes; i++)
  {
    reproduceMicrobe(_reproducing_microbe[i]);
  }
  
  for (unsigned i = 0; i < _num_evolving_microbes; i++)
  {
    evolveMicrobe(_evolving_microbe[i]);
  }
}

void Simulation::orderSpeedyMicrobe(int i, int dM, float dT)
{
  _order[i].turn = Math_clamp(_order[i].turn, -1.0f, 1.0f);
  
  if (_microbe[i].action == MICROBE_ACTION_REPRODUCING)
  {
    _microbe[i].action_time += dM;
    
    if (_microbe[i].action_time >= SPEEDY_MICROBE_REPRODUCE_TIME)
    {
      _microbe[i].action = MICROBE_ACTION_NONE;
      _microbe[i].action_time = 0;
      
      _reproducing_microbe[_num_reproducing_microbes++] = &_microbe[i];
    }
  }
  else if (_microbe[i].action == MICROBE_ACTION_EVOLVING)
  {
    _microbe[i].action_time += dM;
    
    if (_microbe[i].action_time >= SOLDIER_MICROBE_EVOLVE_TIME)
    {
      _microbe[i].action = MICROBE_ACTION_NONE;
      _microbe[i].action_time = 0;
      
      _evolving_microbe[_num_evolving_microbes++] = &_microbe[i];
    }
  }
  else
  {
    if (_order[i].reproduce &&
      _player[_microbe[i].player_id].food >= SPEEDY_MICROBE_REPRODUCE_COST)
    {
      _microbe[i].action = MICROBE_ACTION_REPRODUCING;
      _microbe[i].action_time = 0;
      
      _player[_microbe[i].player_id].food -= SPEEDY_MICROBE_REPRODUCE_COST;
    }
    else if (_order[i].evolve &&
      _player[_microbe[i].player_id].food >= SOLDIER_MICROBE_EVOLVE_COST)
    {
      _microbe[i].action = MICROBE_ACTION_EVOLVING;
      _microbe[i].action_time = 0;
      
      _player[_microbe[i].player_id].food -= SOLDIER_MICROBE_EVOLVE_COST;
    }
    else
    {
      _microbe[i].angle += SPEEDY_MICROBE_TURN_SPEED * _order[i].turn * dT;
      _microbe[i].angle = Math_angleWrap360(_microbe[i].angle);
      _microbe[i].body.pos.x +=
        SPEEDY_MICROBE_SPEED * Math_cosd(_microbe[i].angle) * dT;
      _microbe[i].body.pos.y +=
        SPEEDY_MICROBE_SPEED * Math_sind(_microbe[i].angle) * dT;
    }
  }
}

void Simulation::orderSoldierMicrobe(int i, int dM, float dT)
{
  _order[i].turn = Math_clamp(_order[i].turn, -1.0f, 1.0f);
  _order[i].move = Math_clamp(_order[i].move, -1.0f, 1.0f);
  
  if (_microbe[i].action == MICROBE_ACTION_ATTACKING)
  {
    Vector2 dir;
    float p;
    
    _microbe[i].action_time += dM;
    
    p = (float)_microbe[i].action_time / SOLDIER_MICROBE_ATTACK_TIME;
    Vector2_fromAngle(&dir, _microbe[i].angle);
    
    _microbe[i].tentacle.p1 = _microbe[i].body.pos;
    _microbe[i].tentacle.p2 = _microbe[i].body.pos +
      SOLDIER_MICROBE_SIGHT_RADIUS * p * dir;
    
    if (_microbe[i].action_time >= SOLDIER_MICROBE_ATTACK_TIME)
    {
      _microbe[i].action = MICROBE_ACTION_RELOADING;
      _microbe[i].action_time = 0;
    }
  }
  else if (_microbe[i].action == MICROBE_ACTION_RELOADING)
  {
    Vector2 dir;
    float p;
    
    _microbe[i].action_time += dM;
    
    p = 1.0f - (float)_microbe[i].action_time / SOLDIER_MICROBE_RELOAD_TIME;
    Vector2_fromAngle(&dir, _microbe[i].angle);
    
    _microbe[i].tentacle.p1 = _microbe[i].body.pos;
    _microbe[i].tentacle.p2 = _microbe[i].body.pos +
      SOLDIER_MICROBE_SIGHT_RADIUS * p * dir;
    
    if (_microbe[i].action_time >= SOLDIER_MICROBE_RELOAD_TIME)
    {
      _microbe[i].action = MICROBE_ACTION_NONE;
      _microbe[i].action_time = 0;
    }
  }
  else if (_microbe[i].action == MICROBE_ACTION_REPRODUCING)
  {
    _microbe[i].action_time += dM;
    
    if (_microbe[i].action_time >= SOLDIER_MICROBE_REPRODUCE_TIME)
    {
      _microbe[i].action = MICROBE_ACTION_NONE;
      _microbe[i].action_time = 0;
      
      _reproducing_microbe[_num_reproducing_microbes++] = &_microbe[i];
    }
  }
  else if (_microbe[i].action == MICROBE_ACTION_EVOLVING)
  {
    _microbe[i].action_time += dM;
    
    if (_microbe[i].action_time >= BIG_DADDY_MICROBE_EVOLVE_TIME)
    {
      _microbe[i].action = MICROBE_ACTION_NONE;
      _microbe[i].action_time = 0;
      
      _evolving_microbe[_num_evolving_microbes++] = &_microbe[i];
    }
  }
  else
  {
    if (_order[i].attack)
    {
      _microbe[i].action = MICROBE_ACTION_ATTACKING;
      _microbe[i].action_time = 0;
    }
    else if (_order[i].reproduce &&
      _player[_microbe[i].player_id].food >= SOLDIER_MICROBE_REPRODUCE_COST)
    {
      _microbe[i].action = MICROBE_ACTION_REPRODUCING;
      _microbe[i].action_time = 0;
      
      _player[_microbe[i].player_id].food -= SOLDIER_MICROBE_REPRODUCE_COST;
    }
    else if (_order[i].evolve &&
      _player[_microbe[i].player_id].food >= BIG_DADDY_MICROBE_EVOLVE_COST)
    {
      _microbe[i].action = MICROBE_ACTION_EVOLVING;
      _microbe[i].action_time = 0;
      
      _player[_microbe[i].player_id].food -= BIG_DADDY_MICROBE_EVOLVE_COST;
    }
    else
    {
      _microbe[i].angle += SOLDIER_MICROBE_TURN_SPEED * _order[i].turn * dT;
      _microbe[i].angle = Math_angleWrap360(_microbe[i].angle);
      
      float move_angle = Math_angleWrap360(_microbe[i].angle + 90.0f);
      
      _microbe[i].body.pos.x +=
        SOLDIER_MICROBE_SPEED * _order[i].move * Math_cosd(move_angle) * dT;
      _microbe[i].body.pos.y +=
        SOLDIER_MICROBE_SPEED * _order[i].move * Math_sind(move_angle) * dT;
    }
  }
}

void Simulation::orderBigDaddyMicrobe(int i, int dM, float dT)
{
  _order[i].move = Math_clamp(_order[i].move, 0.0f, 1.0f);
  _order[i].angle = Math_angleWrap360(_order[i].angle);
  
  if (_microbe[i].action == MICROBE_ACTION_RELOADING)
  {
    _microbe[i].action_time += dM;
    
    if (_microbe[i].action_time >= BIG_DADDY_MICROBE_RELOAD_TIME)
    {
      _microbe[i].action = MICROBE_ACTION_NONE;
      _microbe[i].action_time = 0;
    }
  }
  else
  {
    if (_order[i].attack)
    {
      Vector2 pos;
      
      _microbe[i].action = MICROBE_ACTION_RELOADING;
      _microbe[i].action_time = 0;
      
      pos.x = _microbe[i].body.pos.x +
        1.05f * BIG_DADDY_MICROBE_RADIUS * Math_cosd(_order[i].angle);
      pos.y = _microbe[i].body.pos.y +
        1.05f * BIG_DADDY_MICROBE_RADIUS * Math_sind(_order[i].angle);
      
      addBullet(_microbe[i].player_id, pos, _order[i].angle);
    }
    else
    {
      _microbe[i].body.pos.x += BIG_DADDY_MICROBE_SPEED * _order[i].move *
        Math_cosd(_order[i].angle) * dT;
      _microbe[i].body.pos.y += BIG_DADDY_MICROBE_SPEED * _order[i].move *
        Math_sind(_order[i].angle) * dT;
    }
  }
}

void Simulation::handleSoldierAttack(int index)
{
  Circle food_circle;
  
  for (unsigned i = 0; i < _num_food; i++)
  {
    if (_food[i].alive)
    {
      food_circle.pos = _food[i].pos;
      food_circle.radius = SIM_FOOD_RADIUS;
      
      if (food_circle.intersect(_microbe[index].tentacle))
      {
        _food[i].alive = false;
        
        _player[_microbe[index].player_id].food += SIM_FOOD_VALUE;
      }
    }
  }
  
  for (unsigned i = 0; i < _num_microbes; i++)
  {
    if (!_microbe[i].alive ||
        _microbe[i].player_id == _microbe[index].player_id)
    {
      continue;
    }
    
    if (_microbe[i].body.intersect(_microbe[index].tentacle))
    {
      _microbe[i].alive = false;
    }
  }
}

void Simulation::reproduceMicrobe(Microbe* microbe)
{
  Vector2 dir;
  Vector2 pos2;
  float r = microbe->body.radius * 1.05f;
  
  Vector2_fromAngle(&dir, microbe->angle);
  
  pos2 = microbe->body.pos - r * dir;
  
  microbe->body.pos += r * dir;
  
  addMicrobe(microbe->type, microbe->player_id, pos2,
    Math_angleWrap360(microbe->angle + 180.0f));
}

void Simulation::evolveMicrobe(Microbe* microbe)
{
  if (microbe->type == MICROBE_SPEEDY)
  {
    microbe->type = MICROBE_SOLDIER;
    microbe->body.radius = SOLDIER_MICROBE_RADIUS;
    microbe->sight = SOLDIER_MICROBE_SIGHT_RADIUS;
  }
  else
  {
    microbe->type = MICROBE_BIG_DADDY;
    microbe->body.radius = BIG_DADDY_MICROBE_RADIUS;
    microbe->sight = BIG_DADDY_MICROBE_SIGHT_RADIUS;
  }
}

void Simulation::collideMicrobes()
{
  for (unsigned i = 0; i < _num_microbes; i++)
  {
    if (!_microbe[i].alive)
    {
      continue;
    }
    
    for (unsigned j = 0; j < _num_microbes; j++)
    {
      if (!_microbe[j].alive || _microbe[i].player_id == _microbe[j].player_id)
      {
        continue;
      }
      
      if (_microbe[i].body.intersect(_microbe[j].body))
      {
        _microbe[i].alive = false;
        _microbe[j].alive = false;
      }
    }
  }
}

void Simulation::removeDeadMicrobes()
{
  unsigned old_num_microbes = _num_microbes;
  
  _num_microbes = 0;
  
  for (unsigned i = 0; i < old_num_microbes; i++)
  {
    if (_microbe[i].alive)
    {
      _microbe[_num_microbes++] = _microbe[i];
    }
    else
    {
      _microbe_id_gen.delId(_microbe[i].id);
    }
  }
}

void Simulation::eatFood()
{
  int cost[SIM_MAX_PLAYERS];
  
  for (unsigned i = 0; i < _num_players; i++)
  {
    cost[i] = 0;
  }
  
  for (unsigned i = 0; i < _num_microbes; i++)
  {
    if (_microbe[i].type == MICROBE_SPEEDY)
    {
      cost[_microbe[i].player_id] += SPEEDY_MICROBE_COST;
    }
    else if (_microbe[i].type == MICROBE_SOLDIER)
    {
      cost[_microbe[i].player_id] += SOLDIER_MICROBE_COST;
    }
    else
    {
      cost[_microbe[i].player_id] += BIG_DADDY_MICROBE_COST;
    }
  }
  
  for (unsigned i = 0; i < _num_players; i++)
  {
    _player[i].food -= cost[i];
    
    if (_player[i].food < 0)
    {
      _player[i].food = 0;
    }
  }
}

void Simulation::calcDone()
{
  int num_alive_players = 0;
  int alive_player = -1;
  
  for (unsigned i = 0; i < _num_players; i++)
  {
    _player[i].alive = false;
  }
  
  for (unsigned i = 0; i < _num_microbes; i++)
  {
    _player[_microbe[i].player_id].alive = true;
  }
  
  for (unsigned i = 0; i < _num_players; i++)
  {
    if (_player[i].food <= 0)
    {
      _player[i].alive = false;
      
      for (unsigned j = 0; j < _num_microbes; j++)
      {
        if (_microbe[j].player_id == i)
        {
          _microbe[j].alive = false;
        }
      }
    }
  }
  
  removeDeadMicrobes();
  
  for (unsigned i = 0; i < _num_players; i++)
  {
    if (_player[i].alive)
    {
      num_alive_players++;
      
      alive_player = i;
    }
    else
    {
      _player[i].food = 0;
    }
  }
  
  if (num_alive_players <= 1)
  {
    _done = true;
    _winner = alive_player;
  }
}

void Simulation::drawMicrobeSight(const Microbe* microbe)
{
  if (microbe->type == MICROBE_SOLDIER)
  {
    float a1 = Math_angleWrap360(microbe->angle - 45.0f);
    float a2 = Math_angleWrap360(microbe->angle + 45.0f);
    
    Draw2D_drawArc(microbe->body.pos, microbe->sight, a1, a2, 24,
      Colour::L_GREY);
  }
  else
  {
    Draw2D_drawCircle(microbe->body.pos, microbe->sight, 32,
      Colour::L_GREY);
    }
}

void Simulation::drawMicrobe(const Microbe* microbe)
{
  Colour colour = _player[microbe->player_id].colour;
  
  if (microbe->type == MICROBE_SOLDIER &&
    (microbe->action == MICROBE_ACTION_ATTACKING ||
     microbe->action == MICROBE_ACTION_RELOADING))
  {
    Draw2D_drawLine(microbe->tentacle.p1, microbe->tentacle.p2, Colour::BLACK);
  }
  
  Draw2D_fillCircle(microbe->body.pos, microbe->body.radius, 16, colour);
  Draw2D_drawCircle(microbe->body.pos, microbe->body.radius, 16, Colour::BLACK);
}

void Simulation::drawBullets()
{
  for (unsigned i = 0; i < _num_bullets; i++)
  {
    Draw2D_fillCircle(_bullet[i].pos, BULLET_RADIUS, 6, Colour::BLACK);
  }
}

void Simulation::drawStats()
{
  int y = 0;
  char string[256];
  
  for (unsigned i = 0; i < _num_players; i++)
  {
    sprintf(string, "Player %u: %u", i + 1, _player[i].food);
    
    GUI_print(Point(0, y), Colour::BLACK, string);
    
    y += 20;
  }
}

void Simulation::drawGameInfo()
{
  GUI_print(Point(100, 100), Colour::BLACK, "DONE");
}
